home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Power 1997 December
/
MACPOWER-1997-12.ISO.7z
/
MACPOWER-1997-12.ISO
/
AMUG
/
PROGRAMMING
/
WASTE Object Handlers 1.2.6.sit
/
WASTE Object Handlers 1.2.6
/
Handler Source
/
WE_snd_Handler.c
< prev
Wrap
Text File
|
1997-07-21
|
10KB
|
411 lines
// Sound Object Handler for the WASTE Text Engine
// by Michael F. Kamprath, kamprath@kagi.com
// maintenance by John C. Daub, hsoi@eden.com
//
// v1.0, 16 March 1995
// v1.0.1, 13 May 1995, changed the sound playing code a little. Also added gestalt
// check for sound recording device when CreateNewSoundObject()
// is called.
// v1.1, 5 June 95, Made some changes recomended by Chris Thomas, <THUNDERONE@delphi.com>:
// - Playing an object's sound is done by ultilizing the object's data
// directly rather than making a copy. Using PlaySoundHandle() for
// your sounds still makes a copy.
// - Added the public routines StopCurrentSound() and IsSoundPlaying().
// - Option to have the sound sound created at the handler's initilization.
// - Added InstallSoundObject() to install sound object handler only.
//
// v1.2, 28 March 1996. Bug fixes by John C. Daub <mailto:hsoi@eden.com>
// - Removed a not operator from SoundIsPlaying() so the function works correctly
// - Adjusted CheckSoundStatus() to work with the fixed SoundIsPlaying()
// - Minor updates: more precompiler directives, WASTE 1.2a5 compatability
//
// v1.2.2, 16 July 1996. Added compatability with WASTE 1.2 and CW9
// Restructured installation routines
//
// v1.2.4, 16 January 1997. Removed the declaration of CreateNewSoundChannel()
// from WE_snd_Handler.h. If this file was compiled with "Activate
// C++ Compiler" turned on (then compiling this C file as C++), there
// would be an error of inconsistent linkage because an 'extern'
// object was then getting redeclared as 'static'. Hopefully this won't
// cause any problems for people.
//
// v1.2.5, 25 April 1997. Added a gCurrentSound != nil check in CheckSoundStatus() just to be safe
//
#ifndef _WASTE_
#include "WASTE.h"
#endif
#ifndef __GESTALT__
#include <Gestalt.h>
#endif
#include "WE_snd_Handler.h"
#ifndef _WASTEOBJECTS_
#include "WASTE_Objects.h"
#endif
#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif
//
// Local only routines
//
static OSErr PlayCurrentGlobalSound( void );
static SndChannelPtr CreateNewSoundChannel( void );
//
// Sound Channel and current playing sound pointers
//
static SndChannelPtr gSoundChannel = nil;
static SndListHandle gCurrentSound = nil;
static short gCurSoundHandleStatus = 0;
#define kIsWASTESound 0x0100
void InitSoundObjectHandler( void )
{
#if CREATE_CHANNEL_AT_INIT
gSoundChannel = CreateNewSoundChannel();
#endif
}
OSErr InstallSoundObject( WEReference theWE )
{
OSErr iErr;
#ifdef __cplusplus
static WENewObjectUPP newSndUPP = NewWENewObjectProc(HandleNewSound);
static WEDisposeObjectUPP disposeSndUPP = NewWEDisposeObjectProc(HandleDisposeSound);
static WEDrawObjectUPP drawSndUPP = NewWEDrawObjectProc(HandleDrawSound);
static WEClickObjectUPP clickSndUPP = NewWEClickObjectProc(HandleClickSound);
#else
static WENewObjectUPP newSndUPP = NULL;
static WEDisposeObjectUPP disposeSndUPP = NULL;
static WEDrawObjectUPP drawSndUPP = NULL;
static WEClickObjectUPP clickSndUPP = NULL;
if ( newSndUPP == NULL )
newSndUPP = NewWENewObjectProc(HandleNewSound);
if ( disposeSndUPP == NULL )
disposeSndUPP = NewWEDisposeObjectProc(HandleDisposeSound);
if ( drawSndUPP == NULL )
drawSndUPP = NewWEDrawObjectProc(HandleDrawSound);
if ( clickSndUPP == NULL )
clickSndUPP = NewWEClickObjectProc(HandleClickSound);
#endif
if ( newSndUPP != NULL )
iErr = WEInstallObjectHandler(kTypeSound, weNewHandler, (UniversalProcPtr)newSndUPP, theWE);
else
iErr = weUnknownObjectTypeErr;
if (iErr) return(iErr);
if ( disposeSndUPP != NULL )
iErr = WEInstallObjectHandler(kTypeSound, weDisposeHandler, (UniversalProcPtr)disposeSndUPP, theWE);
else
iErr = weUnknownObjectTypeErr;
if (iErr) return(iErr);
if ( drawSndUPP != NULL )
iErr = WEInstallObjectHandler(kTypeSound, weDrawHandler, (UniversalProcPtr)drawSndUPP, theWE);
else
iErr = weUnknownObjectTypeErr;
if (iErr) return(iErr);
if ( clickSndUPP != NULL )
iErr = WEInstallObjectHandler(kTypeSound, weClickHandler, (UniversalProcPtr)clickSndUPP, theWE);
else
iErr = weUnknownObjectTypeErr;
if (iErr) return(iErr);
return(noErr);
}
//
// New Object Handler for sounds
//
pascal OSErr HandleNewSound(Point *defaultObjectSize,WEObjectReference objectRef)
{
#pragma unused (objectRef)
(*defaultObjectSize).h = 32;
(*defaultObjectSize).v = 32;
return(noErr);
}
//
// Dispose Object handler for sounds
//
pascal OSErr HandleDisposeSound(WEObjectReference objectRef )
{
SndListHandle theSound;
theSound = (SndListHandle)WEGetObjectDataHandle(objectRef);
if (theSound == gCurrentSound)
StopCurrentSound();
DisposeHandle((Handle)theSound);
return(MemError());
}
//
// Draw Object handler for sounds
//
pascal OSErr HandleDrawSound(Rect *destRect, WEObjectReference objectRef )
{
#pragma unused (objectRef)
OSErr iErr;
iErr = PlotIconID(destRect,atNone,ttNone,kSoundIconID);
return( iErr );
}
//
// Click Object Handler for sounds
//
pascal Boolean HandleClickSound( Point hitPt,
short modifiers,
long clickTime,
WEObjectReference objectRef)
{
#pragma unused ( hitPt, clickTime)
OSErr iErr;
if (modifiers & 0x0001) // look for double-clicks
{
iErr = StopCurrentSound();
gCurrentSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
iErr = PlayCurrentGlobalSound();
gCurSoundHandleStatus += kIsWASTESound;
if (!iErr)
return(true);
else
{
StopCurrentSound();
return(false);
}
}
else
return(false);
}
//
// PlaySelectedSound()
// If a sound object, and only a sound object, is selected,
// PlaySelectedSound() will play it.
//
OSErr PlaySelectedSound( WEReference theWE )
{
WEObjectReference objectRef;
SndListHandle theSound;
OSErr iErr = noErr;
iErr = WEGetSelectedObject( &objectRef, theWE );
if (!iErr)
{
theSound = (SndListHandle)WEGetObjectDataHandle( objectRef );
iErr = PlaySoundHandle( theSound );
}
return( iErr );
}
//
// CreateNewSoundObject()
// Uses built in sound recording to create a new sound object.
//
OSErr CreateNewSoundObject( WEReference theWE )
{
OSErr iErr;
SndListHandle sndHandle = nil;
long gestaltResponse;
Point corner = {32,32};
iErr = Gestalt(gestaltSoundAttr, &gestaltResponse);
if ( (iErr == noErr)&&(gestaltResponse&gestaltHasSoundInputDevice))
{
iErr = SndRecord(nil,corner,siGoodQuality,&sndHandle);
if (iErr == noErr)
{
corner.h = 32;
corner.v = 32;
WEInsertObject( kTypeSound, (Handle)sndHandle, corner, theWE );
}
}
return( iErr );
}
//
// PlaySoundHandle()
// Ultility routine to play a sound async. Maintains a sound channel
// and the sound data to do so.
//
// Intended for use by external code.
//
OSErr PlaySoundHandle( SndListHandle theSound )
{
OSErr iErr = noErr;
// If a sound is currently playing, stop it and dispose of it's buffer.
iErr = StopCurrentSound();
// create a new buffer for the selected sound.
gCurrentSound = theSound;
iErr = HandToHand((Handle *)&(gCurrentSound));
if (!iErr)
{
iErr = PlayCurrentGlobalSound();
if (iErr)
{
// FYI, HLock is called in PlayCurrentGlobalSound()
HUnlock( (Handle)gCurrentSound );
DisposeHandle( (Handle)gCurrentSound );
gCurrentSound = nil;
}
}
return(iErr);
}
//
// PlayCurrentGlobalSound()
// Used locally by the object handler to play the current sound.
//
static OSErr PlayCurrentGlobalSound( void )
{
OSErr iErr = noErr;
// check for sound channel
if (!gSoundChannel)
gSoundChannel = CreateNewSoundChannel();
if (gCurrentSound&&gSoundChannel)
{
// Lock the buffer and play the sound.
gCurSoundHandleStatus = HGetState( (Handle)gCurrentSound );
HLockHi( (Handle)gCurrentSound );
// FYI, gCurrentSound is unlocked and disposed of upon return to
// PlaySoundHandle()
iErr = SndPlay(gSoundChannel,gCurrentSound,true);
}
return(iErr);
}
//
// StopCurrentSound()
// Stops the current sound and returns memory to original state.
//
OSErr StopCurrentSound( void )
{
SndCommand cmd;
OSErr iErr;
if (gCurrentSound&&gSoundChannel)
{
cmd.cmd = quietCmd;
iErr = SndDoImmediate(gSoundChannel,&cmd);
HSetState( (Handle)gCurrentSound, (char)(gCurSoundHandleStatus&0x00FF) );
iErr = MemError();
if (iErr) return(iErr);
if (!(gCurSoundHandleStatus&kIsWASTESound))
DisposeHandle( (Handle)gCurrentSound );
gCurrentSound = nil;
gCurSoundHandleStatus = 0;
return(MemError());
}
return(noErr);
}
//
// CreateNewSoundChannel()
// Used to create a new shound channel.
//
static SndChannelPtr CreateNewSoundChannel( void )
{
OSErr iErr;
SndChannelPtr chan;
// allocate a sound channel
chan = (SndChannelPtr)NewPtrClear(sizeof(SndChannel));
if ( chan != nil )
{
chan->qLength = stdQLength; //128 sound commands
iErr = SndNewChannel(&chan, sampledSynth, 0, nil);
if (iErr)
{
DisposePtr((Ptr)chan);
chan = nil;
}
}
return(chan); // return SndChannelPtr
}
//
// CheckSoundStatus()
// Should be called periodically to dispose of unneeded sound buffers.
//
void CheckSoundStatus( void )
{
if ((!SoundIsPlaying()) && (gCurrentSound !=nil))
{
HSetState( (Handle)gCurrentSound, (char)(gCurSoundHandleStatus&0x00FF) );
if (!gCurSoundHandleStatus&kIsWASTESound)
DisposeHandle( (Handle)gCurrentSound );
gCurrentSound = nil;
gCurSoundHandleStatus = 0;
}
}
//
// SoundIsPlaying()
// Returns true if a sound is being played by the object handler,
// false if not.
//
Boolean SoundIsPlaying( void )
{
OSErr iErr;
SCStatus theStatus;
if (gSoundChannel)
{
iErr = SndChannelStatus(gSoundChannel,sizeof(SCStatus),&theStatus);
if (( theStatus.scChannelBusy )&&(gCurrentSound))
return( true );
}
return( false );
}